package util;

import game.Game;
import gfx.Camera;
import gfx.GLRenderer;
import android.app.Activity;
import android.graphics.PointF;
import android.view.MotionEvent;

public class InputHandler {
	private Camera mCamera;
	private Game game;
	
	private float downX;
	private float downY;

	private float moveX;
	private float moveY;
	PointF GLLocation;
//	PointF WorldLocation;
//	PointF ScreenLocation;
	PointF tempPointF;
	
	public static final int INPUT_TAP = 0;
	public static final int INPUT_DOWN = 1;
	public static final int INPUT_UP = 2;
	public static final int INPUT_DRAG = 3;
	public static final int INPUT_ZOOM = 4;
	public static final int INPUT_MENU = 5;
	
	private boolean down = false;
	
	private InputHandler(){};

	private static class InputHandlerHolder {
		public static final InputHandler instance = new InputHandler();
	}

	public static InputHandler getInstance(){
		return InputHandlerHolder.instance;
	}
	
	public void init(Activity mActivity, Game game){
		this.game = game;
		mCamera = Camera.getInstance();
		downX = -1;
		downY = -1;

		moveX = -1;
		moveY = -1;

		GLLocation = new PointF();
//		WorldLocation = new PointF();
//		ScreenLocation = new PointF();
		tempPointF = new PointF();

	}
	
	public void handleTouchEvent(MotionEvent e) throws Exception{
		if(!GLRenderer.isLoaded()) return;
		
//		ScreenLocation.set(e.getX(), e.getY());
		GLLocation.set(mCamera.getGLX(e.getX()), mCamera.getGLY(e.getY()));

		switch(e.getAction() & MotionEvent.ACTION_MASK){
		//Another finger is detected.
		case MotionEvent.ACTION_POINTER_DOWN:
			// If true, probably means we want to zoom (in this implementation)
			break;
		case MotionEvent.ACTION_DOWN:
//			Logger.log("Touch: " + e.getX() + " | " + e.getY());
			if(downX < 0){ //&& startY < 0){
				downX = mCamera.getGLX(e.getX());
				downY = mCamera.getGLY(e.getY());
			}
			down = true;
//			handler.post(downLoop);
			break;
//		case MotionEvent.ACTION_POINTER_UP:
		case MotionEvent.ACTION_UP:
			down = false;
//			handler.removeCallbacks(downLoop);

			sendAction(INPUT_UP, GLLocation);
			downX = -1;
			downY = -1;
			moveX = -1;
			moveY = -1;
			break;
		case MotionEvent.ACTION_MOVE:
//			Logger.log("[InputManager]: Move");
			if(moveX >= 0) {			
				sendAction(INPUT_DRAG,GLLocation);
			}
			moveX = e.getX();
			moveY = e.getY();
			break;
		}
	}
	
	public void sendAction(int action, PointF location) throws Exception{
		switch(action){
		case INPUT_TAP:
//			Logger.log("Tap: Pixel  x: " + location.x + " y: " + location.y);
//			Logger.log("Screen x: " + GLLocation.x + " y: " + GLLocation.y);
//			Logger.log("World  x: " + WorldLocation.x + " y: " + WorldLocation.y);
			break;
		case INPUT_UP:
//			Logger.log("Up: x: " + location.x + " y: " + location.y);
			game.handleUp(location);
			break;
		case INPUT_DOWN:
//			Logger.log("Down: x: " + location.x + " y: " + location.y);
			game.handleTouch(location);
			break;
		case INPUT_DRAG:
//			Logger.log("Drag: X: " + location.x + " | " + location.y);
			game.handleDrag(location);
			break;
		case INPUT_MENU:
//			Logger.log("[InputManager] - Menu pressed!");
			break;

		}
	}
	
	// Replaced the Thread with a tick and boolean.
	public void tick(){
		if(down){
			tempPointF.set(downX, downY);
			try {
				sendAction(INPUT_DOWN, tempPointF);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
//	private Handler handler = new Handler();
//	private Runnable downLoop = new Runnable(){
//		@Override
//		public void run() {
//			tempPointF.set(downX,downY);
//			try {
//				sendAction(INPUT_DOWN, tempPointF);
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//			handler.postDelayed(downLoop, 100);//Send every 100ms
//		}
//	};
}
